package br.unifor.ia;

import java.awt.Canvas;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;

/**
 * Classe que vai representar o ambiente em forma de gráfico.
 * @author pedro
 */
public class Cenario extends Canvas implements Runnable, KeyListener {

    /**
     * Imagem auxiliar.
     */
    private Image img;
    /**
     * Gráfico auxiliar.
     */
    private Graphics gr;
    /**
     * Agente.
     */
    private SimpleAgent agent;
    /**
     * Posição auxiliar.
     */
    private Posicao posAux;
    /**
     * Ambiente.
     */
    private Ambiente ambiente;
    /**
     * Imagem de objeto.
     */
    public Image sabinUp,  sabinDn,  sabinLf,  sabinRg,  monstro,  cenario,  ouro,  buraco,cano,monstroRm;
    /**
     * Altura do canvas e da Tela.
     */
    public static final int HEIGHT_CANVAS = 500;
    /**
     * Largura do canvas e da Tela.
     */
    public static final int WIDTH_CANVAS = 640;
    /**
     * O tamanho de uma unidade de área, cada unidade de área representa uma célula da matriz da classe ambiente.
     */
    public static final int UNID_AREA = 20;
    /**
     * Imagem selecionada para o personagem no momento, a seleção depende da direção do personagem.
     */
    private Image imagSel;
    /**
     * Quantidade de ouros encontrados.
     */
    private int quantOuroEnc;    

    /**
     * Construtor
     */
    public Cenario() {
        sabinUp = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/sabinUp.gif")).getImage();
        sabinDn = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/sabinDn.gif")).getImage();
        sabinLf = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/sabinLf.gif")).getImage();
        sabinRg = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/sabinRg.gif")).getImage();
        cenario = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/cenario.png")).getImage();
        monstro = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/monstro.gif")).getImage();
        ouro = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/ouro.gif")).getImage();
        buraco = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/buraco.gif")).getImage();
        cano = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/cano.png")).getImage();
        monstroRm = new ImageIcon(getClass().getClassLoader().getResource("br/unifor/ia/img/monstro.gif")).getImage();
        setSize(Cenario.WIDTH_CANVAS, Cenario.HEIGHT_CANVAS);
        ambiente = new Ambiente();
        agent = new SimpleAgent();
        agent.start();
        new Thread(this).start();
    }

    @Override
    public void update(Graphics g) {
        if (img == null) {
            img = createImage(this.getWidth(), this.getHeight());
            gr = img.getGraphics();
        }
        gr.setColor(this.getBackground());
        gr.fillRect(0, 0, this.getWidth(), this.getHeight());
        paint(gr);
        g.drawImage(img, 0, 0, null);
    }

    @Override
    public void paint(Graphics g) {
        //cenário        
        g.drawImage(cenario, 0, 0, null);
        //wumpus        
        paintWumpus(g);
        //ouro
        paintOuro(g);
        //buraco
        paintBuraco(g);
        //checar se soltou flecha
        if (agent.isSoltouFlecha()) {
            ambiente.atirarFlecha(agent);
        }
        //personagem        
        if (!agent.isGameOver()) {
            ambiente.moverPersonagem(agent);
        }
        paintPersonagem(g);
        //cano
        g.drawImage(cano, 30, 440, null);
    }

    public void run() {
        while (true) {
            this.repaint();
            try {
                Thread.sleep(Constantes.TEMPO_THREAD_AGENT);
            } catch (InterruptedException ex) {
                Logger.getLogger(Cenario.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     * 'Pinta' o personagem.
     * @param g O gráfico da tela corrente.
     */
    private void paintPersonagem(Graphics g) {
        posAux = Funcoes.calculaPosGraph(agent.getPos());
        setImgPers();
        if (!agent.isSugado()) {
            g.drawImage(imagSel, posAux.getX(), posAux.getY(), null);
        }
        if (agent.isGameOver()) {
            g.setColor(Color.RED);
            g.drawString("GAME OVER!!", 305, 270);
        }
        if (agent.isVenceu()) {
            g.setColor(Color.BLUE);
            g.drawString("VOCÊ VENCEU!!", 305, 270);
        }
    }

    /**
     * 'Pinta' o monstro.
     * @param g O gráfico da tela corrente.
     */
    private void paintWumpus(Graphics g) {
        posAux = Funcoes.calculaPosGraph(ambiente.getWumpusPos());
        if (!ambiente.isWumpusRemovido()) {
            g.drawImage(monstro, posAux.getX(), posAux.getY(), null);
            g.drawImage(monstro, 0, 25, null);
        }
        else
        {
            g.drawImage(monstroRm, 0, 25, null);
        }

    }

    /**
     * 'Pinta' o buraco.
     * @param g O gráfico da tela corrente.
     */
    private void paintBuraco(Graphics g) {
        for (int i = 0; i < ambiente.getBuracos().size(); i++) {
            posAux = Funcoes.calculaPosGraph(ambiente.getBuracos().elementAt(i));
            g.drawImage(buraco, posAux.getX(), posAux.getY(), null);
        }

    }

    /**
     * 'Pinta' o ouro.
     * @param g O gráfico da tela corrente.
     */
    private void paintOuro(Graphics g) {
        if (agent.isAchouOuro()) {
            if (!ambiente.isOuroRemovido()) {
                ambiente.removerObjeto(Ambiente.SIMB_OURO);
                quantOuroEnc = 1;
            }
        } else {
            posAux = Funcoes.calculaPosGraph(ambiente.getOuroPos());
            g.drawImage(ouro, posAux.getX(), posAux.getY(), null);
        }

        g.drawImage(ouro, 0, -5, null);
        g.drawString("" + quantOuroEnc, 35, 15);

    }

    /**
     * Seta a imagem no personagem de acordo com a direção do próprio.
     */
    private void setImgPers() {
        switch (agent.getDirecao()) {
            case Agente.AGENT_LEFT:
                imagSel = sabinLf;
                break;
            case Agente.AGENT_UP:
                imagSel = sabinUp;
                break;
            case Agente.AGENT_RIGHT:
                imagSel = sabinRg;
                break;
            case Agente.AGENT_DOWN:
                imagSel = sabinDn;
                break;
        }
    }

    public void keyTyped(KeyEvent arg0) {

    }

    /**
     * Método para 'escuta' do teclado em caso de testes, caso alguma tecla seja pressionada o agente é desabilitado e o teclado assume o controle do agente.
     * @param arg0
     */
    public void keyPressed(KeyEvent arg0) {
        if (!agent.isModoTeste()) {
            agent.setModoTeste(true);
        }
        int keyCode = arg0.getKeyCode();
        switch (keyCode) {
            case KeyEvent.VK_UP: {
                agent.setDirecao(Agente.AGENT_UP);
                break;
            }
            case KeyEvent.VK_DOWN: {
                agent.setDirecao(Agente.AGENT_DOWN);
                break;
            }
            case KeyEvent.VK_LEFT: {
                agent.setDirecao(Agente.AGENT_LEFT);
                break;
            }
            case KeyEvent.VK_RIGHT: {
                agent.setDirecao(Agente.AGENT_RIGHT);
                break;
            }
        }

    }

    public void keyReleased(KeyEvent arg0) {


    }
}
